# -*- coding: utf-8 -*-
'''
    :file: files.py
    :author: -Farmer
    :url: https://blog.farmer233.top
    :date: 2021/02/12 16:31:41
'''
import os
import random
# from sys import path
import shutil
from werkzeug.datastructures import FileStorage
from app.utils import is_safe_path, make_share_time
from flask.globals import current_app
from werkzeug.utils import secure_filename
from app.operation.redis_client import Redis_client
# 1. 获取文件
# 2. 上传文件
# 3. 下载文件
# 获取文件信息


class FileOperation(object):
    def __init__(self, username) -> None:
        self.prefix = os.path.join(
            current_app.config['UPLOAD_FOLDER'], username)

    def get_file(self, path="./"):
        """
        @description: 获取当前路径下的所有目录和文件，生成一个字典返回
        ---------
        @param: path;
        -------
        @Returns: dict
        -------
        """
        if not is_safe_path(path):
            raise ValueError('路径不合法')
        try:
            path = os.path.join(self.prefix, path)
            dir_list = os.listdir(path=path)
            datas = {"dirs": [], 'files': []}

            for data in dir_list:
                tmp_path = os.path.join(path, data)
                if os.path.isdir(tmp_path):
                    datas['dirs'].append({
                        'name': data,
                        'date': os.path.getmtime(tmp_path) * 1000,
                        'size': '-',
                        'type': "dir",
                    })
                else:
                    datas['files'].append({
                        'name': data,
                        'date': os.path.getmtime(tmp_path) * 1000,
                        'size': os.path.getsize(tmp_path),
                        'type': os.path.splitext(data)[-1]
                    })
            return datas
        except Exception as e:
            raise e

    def del_file(self, path, filename):
        """
        @description: 根据路径、文件名删除文件
        ---------
        @param: path:str -> 路径
                filename:str -> 文件名
        -------
        @Returns: 操作信息:str
        -------
        """
        if not is_safe_path(path=path):
            raise ValueError('路径不合法')
        location = os.path.join(self.prefix, path, filename)
        if os.path.exists(location) and os.path.isfile(location):
            os.remove(location)
            return "Remove File Success."
        return "File not exists!"


class UploadFile(FileOperation):
    '''   继承自 FileOperation 类，添加了upload方法，将传入的文件保存在指定合法的路径  '''

    def upload(self, path, file: FileStorage):
        if not is_safe_path(path):
            raise ValueError("路径不合法")
        filename = secure_filename(file.filename)
        file.save(os.path.join(self.prefix, path, filename))
        return {
            "path": path,
            "filename": filename
        }


class DownloadFile(FileOperation):
    """   继承自 FileOperation 类, 返回文件的 路径前缀 和 相对路径   """

    def __init__(self, username, path) -> None:
        super().__init__(username)
        self.path = path

    def get_file(self):
        print(self.prefix)
        if not is_safe_path(path=self.path):
            raise ValueError("请求路径不合法")
        path = os.path.join(self.prefix, self.path)
        print(path)
        if os.path.exists(path):
            return path
        raise ValueError("文件不存在")


class FileRename(FileOperation):
    """   继承自 FileOperation 类   """

    def __init__(self, username) -> None:
        super().__init__(username)

    def rename(self, path, old_name, new_name):
        """
        @description: 重命名，根据路径、旧文件名定位文件，然后更改名字
        ---------
        @param: path:str -> 路径, 
                old_name -> 旧文件名
                new_name -> 新文件名
        -------
        @Returns: None
        -------
        """        
        if not is_safe_path(path):
            raise ValueError('路径不合法')
        if not is_safe_path(old_name):
            raise ValueError('文件名不合法')

        old_name = os.path.join(self.prefix, path, old_name)

        new_name = secure_filename(new_name)
        new_name = os.path.join(self.prefix, path, new_name)

        try:
            os.rename(old_name, new_name)
        except FileNotFoundError as e:
            raise e


class MoveFile(FileOperation):

    def __init__(self, username) -> None:
        super().__init__(username)

    def move(self, new_path, old_path, filename):
        ''' 移动文件 '''
        if not is_safe_path(filename):
            raise ValueError('文件名不合法')

        if not is_safe_path(old_path):
            raise ValueError('旧路径不合法')

        if not is_safe_path(new_path):
            raise ValueError('新路径不合法')

        old_path = os.path.join(self.prefix, old_path, filename)
        new_path = os.path.join(self.prefix, new_path, filename)
        shutil.move(old_path, new_path)


class MakeFolder(FileOperation):
    def __init__(self, username) -> None:
        super().__init__(username)

    def make(self, path, folder_name):
        ''' 生成文件夹 '''
        if not is_safe_path(path):
            raise ValueError('路径不合法')
        if not is_safe_path(folder_name):
            raise ValueError('路径不合法')
        path = os.path.join(self.prefix, path, folder_name)
        os.mkdir(path)


class ShareFile(FileOperation):

    def __init__(self, username="") -> None:
        super().__init__(username)
        self.username = username

    def make_share_code(self, path, filename, timeout):
        ''' 生成分享码 '''
        share_path = os.path.join(self.username, path, filename)
        path = os.path.join(self.prefix, path, filename)

        if not is_safe_path(share_path):
            raise ValueError('分享文件不正确')

        if not os.path.isfile(path):
            raise ValueError('分享的文件不存在')

        try:
            timeout = make_share_time(timeout)
            # 尝试生成分享码十次
            for _ in range(10):
                share_code = random.randint(10 ** 5, 10 ** 6)
                # 判断生成的分享码是否已存在
                data = Redis_client.read(share_code)
                if data is None:
                    Redis_client.write(
                        key=share_code, value=share_path, expire=timeout)
                    return {
                        "share_code": share_code,
                        "share_time": timeout
                    }
            raise ValueError('生成超时啦！一会再试试吧.')
        except ConnectionError as e:
            raise e
        except Exception as e:
            print(type(e))
            raise e

    def download_share_file(self, share_code):
        ''' 读取分享码对应的资源路径 '''
        share_file = Redis_client.read(share_code)
        if share_file:
            share_file = os.path.join(current_app.config['UPLOAD_FOLDER'], share_file)
            if not is_safe_path(share_file):
                raise ValueError('分享码路径不合法')
            
            share_file = share_file.split(os.sep)
            filename = share_file[-1]
            path = os.sep.join(share_file[:-1])
            return path, filename
        raise ValueError('分享码已过期')

# def download_share_file(share_code):
